package com.wngbms.multidatasource.datasource.mybatis;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.wngbms.multidatasource.bean.MyUser;
import com.wngbms.multidatasource.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Slf4j
public class MybatisTestMulti {

    public static void main(String[] args) throws IOException {
        InputStream stream = Resources.getResourceAsStream("mybatis.xml");

        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        handle(mapper);

        sqlSession.close();
        stream.close();

    }

    static Set<String> mSet = new HashSet<>();

    static {
        mSet.add("equals(java.lang.Object)");
        mSet.add("toString()");
        mSet.add("hashCode()");
        mSet.add("newProxyInstance");
        mSet.add("getInvocationHandler");
        mSet.add("getProxyClass");
        mSet.add("wait()");
        mSet.add("wait(long,int)");
        mSet.add("wait(long)");
        mSet.add("getClass()");
        mSet.add("notify()");
        mSet.add("notifyAll()");
        mSet.add("isProxyClass(java.lang.Class)");
    }

    public static void handle(UserMapper userMapper) {
        Method[] methods = userMapper.getClass().getMethods();

        for (Method method : methods) {
            if (isB(method)) {
                continue;
            }

            try {
                Object[] args = genParam(method);
                log.info("{} {}", method, args);
                Object invoke = method.invoke(userMapper, args);
                log.info("{} {}", method, JSON.toJSONString(invoke));
            } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
                e.printStackTrace();
            }
        }
    }

    private static Object[] genParam(Method method) throws InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?>[] parameterTypes = method.getParameterTypes();

        if (parameterTypes.length == 0) {
            return null;
        } else {
            Object[] os = new Object[parameterTypes.length];
            for (int i = 0; i < parameterTypes.length; i++) {
                os[i] = genParam(parameterTypes[i]);
            }
            return os;
        }
    }

    private static Object genParam(Class<?> c) throws InvocationTargetException, InstantiationException, IllegalAccessException {

        if (c == Integer.class) {
            return 1;
        } else if (c == Long.class) {
            return 1L;
        } else if (c == String.class) {
            return "";
        }

        Constructor<?>[] constructors = c.getConstructors();
        for (Constructor<?> constructor : constructors) {
            if (constructor.getParameterCount() == 0) {
                return constructor.newInstance(null);
            } else {
                return null;
            }
        }
        return null;
    }

    private static boolean isB(Method method) {
        boolean b = false;
        String name = method.getName();
        for (String s : mSet) {
            if (s.contains(name)) {
                b = true;
                break;
            }
        }
        return b;
    }

}
